﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UIWindows.Domains;
using UIWindows.Tools.Helper;
using XingLucifer.IBase;
using XingLucifer.IBase.Enums;
using NewLife.Data;
using UIWindows.GlobalStatics;
using System.IO;
using System.Threading;
using System.Net.Sockets;
using Org.BouncyCastle.Utilities.Encoders;
using Kinlo.Entitys;
using XingLucifer.IBase.Models.PLCInteraktion;
using XingLucifer.Devices;
using Kinlo.MESDocking;

namespace UIWindows.Services.Handle
{
    [Attributes.TaskClass(TaskTypes.前扫码)]
    public class BeforeScanCode : ServierBase
    {
        #region Synchronize
        private volatile int _lock = 0;
        protected void Locked()
        {
            int lockNumber = 0;
            while (Interlocked.Exchange(ref _lock, 1) != 0)
            {
                _ = 0; _ = 0; _ = 0; _ = 0; _ = 0; _ = 0; _ = 0; _ = 0; _ = 0; _ = 0; _ = 0; _ = 0; _ = 0; _ = 0; _ = 0; _ = 0;
                if (++lockNumber > 50)
                {
                    Thread.Sleep(1);
                    lockNumber = 0;
                }
            }
        }

        protected void UnLock() => Interlocked.Exchange(ref _lock, 0);
        #endregion
        private SnowflakeManager _snowflake;
        private IMESInteraction _interactionWorkOrders;
        public BeforeScanCode(DeviceConfigStatic deviceConfig, SystemConfigStatic systemConfig,
            UserConfigStatic userConfig, ParameterStatic parameterStatic, TemporaryStatic temporaryStatic, HomeStatic homeStatic, MesParameterStatic mesParameterStatic)
            : base(deviceConfig, systemConfig, userConfig, parameterStatic, temporaryStatic, homeStatic, mesParameterStatic)
        {
            _snowflake = new SnowflakeManager(12);
            _interaction = new PreventionCheckInterface(DialogLogHelper.MesLog, DialogLogHelper.MESDialog);
            _interactionWorkOrders = new GetByProductCodeInterface(DialogLogHelper.MesLog, DialogLogHelper.MESDialog);
        }

        public override Task Handle(Context.DataContext context)
        {
            if (!ClearSignal(context)) { return Task.CompletedTask; }
            try
            {
                var plc = _deviceConfig.DeviceList.FirstOrDefault(x => x.ServiceName == context.ServiceName && x.TaskType == TaskTypes.扫描信号).Communication as OmronCIP;
                var device = _deviceConfig.DeviceList.FirstOrDefault(x => x.ServiceName == context.ServiceName && x.TaskType == context.TaskType && x.Index == context.DeviceIndex && x.DeviceType == context.DeviceType);
                DateTime dateTime = DateTime.Now;
                ResultTypes resultTypes = ResultTypes.合格;
                long snowflake = _snowflake.NextId();
                string barcode = string.Empty;
                if (_parameterStatic.DecideParameter.EnableEmptyRun || _parameterStatic.DecideParameter.EnablePseudoCode || device == null)
                {
                    barcode = $"Empty{Guid.NewGuid().ToString().Substring(0, 5)}1234567890{new Random().Next(1, 9999):D4}";
                    if (device == null)
                    {
                        RunLog($"-[{context.DeviceIndex}] 触发设备位置找不到，请注意!!!", MessageLevelType.错误);
                    }
                }
                else
                {
                    barcode = ScanCode(_parameterStatic.RunParameter.Retries_Count_ScanCode, device.Communication, context.DeviceIndex);
                }
                _homeStatic.ChartData.Total_Inbound += 1;
                if (barcode == "ERROR")
                {
                    RunLog($"-[{context.DeviceIndex}] 扫码失败", MessageLevelType.信息);
                    _homeStatic.ChartData.NG_ScanCode += 1;
                    resultTypes = ResultTypes.扫码失败;
                    barcode = "NGNGNG";
                }
                else
                {
                    ProductionData.Meta.TableName = $"ProductionData_{DateTime.Now:yyyy}{DateTime.Now.GetQuarterly()}";
                    //string rangeForeweigh = _parameterStatic.DecideParameter.EnableReinvestmentMode 
                    //    ? $"{_parameterStatic.RangeParameter.ReinvestmentWeighBeforeDown}-{_parameterStatic.RangeParameter.ReinvestmentWeighBeforeUp}" 
                    //    : $"{_parameterStatic.RangeParameter.WeighBeforeDown}-{_parameterStatic.RangeParameter.WeighBeforeUp}";
                    //string rangeFluidRate = _parameterStatic.DecideParameter.EnableVariableInjection
                    //        ? $"{_parameterStatic.RangeParameter.VariablesDown}-{_parameterStatic.RangeParameter.Variables}-{_parameterStatic.RangeParameter.VariablesUp}"
                    //        : $"{_parameterStatic.RangeParameter.QuantitativeDown}-{_parameterStatic.RangeParameter.Quantitative}-{_parameterStatic.RangeParameter.QuantitativeUp}";
                    var entity = new ProductionData()
                    {
                        SnowflakeId = snowflake,
                        BarCode = barcode,
                        TimeScanCodeBefore = dateTime.GetJSTimeUtc(),
                        RangeElectrodes = $"{_parameterStatic.RangeParameter.ElectrodesDown}={_parameterStatic.RangeParameter.ElectrodesUP}",
                        RangeAfterWeighing = $"{_parameterStatic.RangeParameter.WeighAfterDown}-{_parameterStatic.RangeParameter.WeighAfterUp}",
                        RangeForeweigh = $"{_parameterStatic.RangeParameter.WeighBeforeDown}-{_parameterStatic.RangeParameter.WeighBeforeUp}",
                        RangeFluidRate = $"{_parameterStatic.RangeParameter.QuantitativeDown}-{_parameterStatic.RangeParameter.Quantitative}-{_parameterStatic.RangeParameter.QuantitativeUp}",
                        BatchElectrolyte = _parameterStatic.CollectionItemsParameter.BatchElectrolyte,
                        ProductType = _parameterStatic.CollectionItemsParameter.ProductType.ToString(),
                        GlueNailBatch = _parameterStatic.CollectionItemsParameter.GlueNailBatch,
                        EquipNum = _parameterStatic.CollectionItemsParameter.EquipNum,
                        ProductionLineNo = _parameterStatic.CollectionItemsParameter.ProductionLineNo,
                        Operator = _temporaryStatic.Mes_Account,
                        ResultTotal = ResultTypes._,
                        ResultScanCodeBefore = ResultTypes.合格,
                        LocationScanCodeBefore = (byte)context.DeviceIndex,
                        WorkOrderNumber = _parameterStatic.CollectionItemsParameter.WorkOrder,
                        ResultOutput = ResultTypes._
                        //CollectionMethod = _parameterStatic.DecideParameter.EnableVariableInjection ? "变量注液" : "定量注液",
                        //ProductionMethod = _parameterStatic.DecideParameter.EnableReinvestmentMode ? "正常" : "复投",
                    };


                    //二注取从其它设备取 电池干重及一注下料重量
                    if (_systemConfig.SCM.MainDeviceType == MainDeviceTypeEnum.二次注液 && _systemConfig.SCM.GetOntData == GetOntDataEnum.其它设备获取)
                    {
                        MySqlHelper mySqlHelper = new MySqlHelper(_parameterStatic.MESParameter.OthenDatabaseurl);
                        var oneData = mySqlHelper.GetBatteryByCode(entity.BarCode);
                        if (oneData.status)
                        {
                            if (oneData.netWeight < 10 || oneData.outputWeight < 10)
                            {
                                entity.ResultScanCodeBefore = ResultTypes.一注数据不在范围;
                                if (entity.ResultTotal == ResultTypes._)
                                    entity.ResultTotal = entity.ResultScanCodeBefore;
                            }
                            else
                            {
                                var twoInj = _parameterStatic.RangeParameter.Quantitative - (oneData.outputWeight - oneData.netWeight);
                                if (twoInj > _parameterStatic.RangeParameter.VariablesUp)
                                {
                                    entity.ResultScanCodeBefore = ResultTypes.变量注液量不在范围;
                                    if (entity.ResultTotal == ResultTypes._)
                                        entity.ResultTotal = entity.ResultScanCodeBefore;
                                }
                            }
                            entity.NetWeight = oneData.netWeight;
                            entity.OneAfterWeighing = oneData.outputWeight;
                        }
                        else
                        {
                            entity.ResultScanCodeBefore = ResultTypes.取一注数据失败;
                            if (entity.ResultTotal == ResultTypes._)
                                entity.ResultTotal = entity.ResultScanCodeBefore;
                        }
                    }

                    for (int i = 0; i < 3; i++)
                    {
                        try
                        {
                            RunLog("开始插入数据库");
                            entity.Insert();
                            Locked();
                            entity.Items.Add("TableName", ProductionData.Meta.TableName);
                            _temporaryStatic.EntityCache.Insert(0, entity);
                            if (_temporaryStatic.EntityCache.Count > 600)
                            {
                                _temporaryStatic.EntityCache.RemoveAt(599);
                            }
                            UnLock();
                            RunLog($"-[{context.DeviceIndex}] ID:[{snowflake}]对应的条码为:[{barcode}] 插入数据库成功");
                            break;
                        }
                        catch (Exception ex)
                        {
                            RunLog($"-[{context.DeviceIndex}] ID:[{snowflake}]对应的条码为:[{barcode}] 第[{i}]次 保存数据库失败：{ex}");
                            if (i == 2) { resultTypes = ResultTypes.扫码NG; }
                            Thread.Sleep(500);
                        }
                    }
                    RunLog($"-[前扫码]条码{entity.BarCode}开始总结果：{entity.ResultTotal}");

                    #region 进站 

                    //进站接口 防呆
                    if (_parameterStatic.DecideParameter.EnableMES && _parameterStatic.DecideParameter.EnablePreventionCheck && resultTypes == ResultTypes.合格)
                    {
                        resultTypes = BatteryInputDataUpload(_interaction, _interactionWorkOrders, entity);
                        //MES没有一二注区分的接口
                        //if (_systemConfig.SCM.MainDeviceType == MainDeviceTypeEnum.一次注液)
                        //{
                        //    resultTypes = BatteryInputDataUpload(_interaction, _interactionWorkOrders, entity);
                        //}
                        //else
                        //{
                        //    //二注取 电池干重及一注下料重量

                        //}
                    }

                    //根据电芯条码获取工单
                    if (_parameterStatic.DecideParameter.EnableMES&& _parameterStatic.DecideParameter.EnableWorkOrderCheck && resultTypes == ResultTypes.合格)
                        resultTypes = GetByProductCode(_interactionWorkOrders, entity);
                    #endregion



                }
                for (int i = 0; i < 3; i++)
                {
                    if (plc.WriteSingle(barcode, $"{context.Address_Struct}.Code"))
                    {
                        RunLog($"-[{context.DeviceIndex}] 条码:[{barcode}] 写入PLC成功!!!");
                        break;
                    }
                    RunLog($"-[{context.DeviceIndex}] 条码:[{barcode}] 写入PLC失败 第[{i}]次");
                }
                BatteryModel model = new BatteryModel();
                model.ID = snowflake;
                model.Results_PC = (short)(resultTypes == ResultTypes.合格 ? 1 : (resultTypes != ResultTypes.MES_NG ? 2 : 3));
                for (int i = 0; i < 3; i++)
                {
                    if (plc.WriteClass(model, $"{context.Address_Struct}.face", 35167))
                    {
                        RunLog($"-[{context.DeviceIndex}] ID:[{model.ID}] 结果:[{model.Results_PC}] 写入成功!!!");
                        break;
                    }
                    RunLog($"-[{context.DeviceIndex}] ID:[{model.ID}] 结果:[{model.Results_PC}] 写入失败 第[{i}]次");
                }
                _homeStatic.AddInBattery(barcode, resultTypes, dateTime, context.DeviceIndex);
            }
            catch (Exception ex)
            {
                RunLog($"异常：{ex}", MessageLevelType.错误);
            }
            return base.Handle(context);
        }
    }
}
